package com.guli.ucenter.controller;

import com.google.gson.Gson;
import com.guli.common.constants.ResultCodeEnum;
import com.guli.common.exception.GuliException;
import com.guli.common.vo.R;
import com.guli.ucenter.entity.Member;
import com.guli.ucenter.service.MemberService;
import com.guli.ucenter.util.ConstantPropertiesUtil;
import com.guli.ucenter.util.HttpClientUtils;
import com.guli.ucenter.util.JwtUtils;
import com.guli.ucenter.vo.LoginInfoVo;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Objects;

/**
 * @author XiaoHua666
 * @date 2019/4/30
 */
@Controller
@CrossOrigin
@RequestMapping("/api/ucenter/wx")
public class WxApiController {
    @Autowired
    private MemberService memberService;

    @GetMapping("/login")
    public String genQrConnect(HttpSession session) {

        String baseUrl = "https://open.weixin.qq.com/connect/qrconnect?" +
                "appid=%s" +
                "&redirect_uri=%s" +
                "&response_type=%s" +
                "&scope=%s" +
                "&state=%s" +
                "#wechat_redirect";
        // 回调地址
        //获取业务服务器重定向地址
        String redirectUrl = ConstantPropertiesUtil.WX_OPEN_REDIRECT_URL;

        try {
            redirectUrl = URLEncoder.encode(redirectUrl, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new GuliException(20001, e.getMessage());
        }
        // 防止csrf攻击（跨站请求伪造攻击）
        //String state = UUID.randomUUID().toString().replaceAll("-", "");//一般情况下会使用一个随机数
        //为了让大家能够使用我搭建的外网的微信回调跳转服务器，这里填写你在ngrok的前置域名
        String state = "wangxiaohua";
        session.setAttribute("wx-open-state", state);
        System.out.println("sessionId " + session.getId());
        System.out.println("state = " + state);

// 采用redis等进行缓存state 使用sessionId为key 30分钟后过期，可配置
        // TODO
        //session.setAttribute("wechar-open-state", state);
        //System.out.println(session.getId());
        //RedisPoolUtil.setEx("wechar-open-state-" + httpServletRequest.getSession().getId(), state, Integer.parseInt(env.getProperty("wechar.open.exTime", "1800")));
        //生成qrcodeUrl

        String qrcodeUrl = String.format(
                baseUrl,
                ConstantPropertiesUtil.WX_OPEN_APP_ID,
                ConstantPropertiesUtil.WX_OPEN_REDIRECT_URL,
                "code",
                "snsapi_login",
                state,
                redirectUrl);
        return "redirect:" + qrcodeUrl;
    }

    @GetMapping("/callback")
    public String callback(String code, String state, HttpSession session) {
        System.out.println("session id " + session.getId());
        System.out.println(code);
        System.out.println(state);
        String stateStr = (String) session.getAttribute("wx-open-state");

        if (StringUtils.isEmpty(code) || StringUtils.isEmpty(state) || !stateStr.equals(stateStr)) {
            throw new GuliException(ResultCodeEnum.INVALID_CALLBACK_REQUEST_ERROR);
        }

        //通过code和APPId及AppSecret 获取AccessKey
        String OauthUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?" +
                "appid=%s&" +
                "secret=%s&" +
                "code=%s&" +
                "grant_type=authorization_code";
        OauthUrl = String.format(OauthUrl,
                ConstantPropertiesUtil.WX_OPEN_APP_ID,
                ConstantPropertiesUtil.WX_OPEN_APP_SECRET,
                code);
        String result = "";
        try {
            result = com.guli.ucenter.util.HttpClientUtils.get(OauthUrl);
        } catch (Exception e) {
            throw new GuliException(ResultCodeEnum.FETCH_ACCESSTOKEN_FAILD);
        }
        //解析远程请求的结果

        Gson gson = new Gson();
        HashMap resultMap = gson.fromJson(result, HashMap.class);
        //判断结果是否异常
        if (resultMap.get("errcode") != null) {
            throw new GuliException(ResultCodeEnum.FETCH_ACCESSTOKEN_FAILD);
        }
        //获取access_token
        String accessToken = (String) resultMap.get("access_token");
        String openid = (String) resultMap.get("openid");
        if (StringUtils.isEmpty(accessToken) || StringUtils.isEmpty(openid)) {
            throw new GuliException(ResultCodeEnum.FETCH_ACCESSTOKEN_FAILD);
        }
        //通过access_token进行接口调用，获取用户基本数据资源或帮助用户实现基本操作：用户登录
        //判断用户是否已经使用微信登陆过系统
        Member member = memberService.getByOpenId(openid);
        if (Objects.isNull(member)) {
            //向数据库中插入用户信息
            //首先携带access_token访问微信的资源服务器上的api，获取微信用户信息
            String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
                    "?access_token=%s" +
                    "&openid=%s";

            String userInfoUrl = String.format(baseUserInfoUrl, accessToken, openid);
            //使用httpclient发送请求
            String resultUserInfo = "";
            try {
                resultUserInfo = HttpClientUtils.get(userInfoUrl);
            } catch (Exception e) {
                e.printStackTrace();
                throw new GuliException(ResultCodeEnum.FETCH_USERINFO_FAILD);
            }

            HashMap<String, Object> resultInfoMap = gson.fromJson(resultUserInfo, HashMap.class);
            //判断结果是否异常
            if (resultInfoMap.get("errcode") != null) {
                throw new GuliException(ResultCodeEnum.FETCH_USERINFO_FAILD);
            }

            String nickname = (String) resultInfoMap.get("nickname");
            String avatar = (String) resultInfoMap.get("headimgurl");
            double sex = (double) resultInfoMap.get("sex");

            //TODO
            //将当前的url头像存储到阿里云服务器，并获取头像在阿里云服务器的url地址

            //生成jwt对象，将jwt存储在cookie中
            member = new Member();
            member.setNickname(nickname);
            member.setAvatar(avatar);

            member.setSex((int)sex);
            member.setOpenid(openid);
            memberService.save(member);
        }

        // TODO 用户登录
        System.out.println("用户登录");

        String guliJwtToken = JwtUtils.generateJWT(member);
        return "redirect:http://localhost:3000?token=" + guliJwtToken;
    }

    @PostMapping("parse-jwt")
    @ResponseBody
    public R getLoginInfoByJwtToken(@RequestBody String jwtToken){

        Claims claims = JwtUtils.checkJWT(jwtToken);

        String id = (String)claims.get("id");
        String nickname = (String)claims.get("nickname");
        String avatar = (String)claims.get("avatar");

        LoginInfoVo loginInfoVo = new LoginInfoVo();
        loginInfoVo.setId(id);
        loginInfoVo.setNickname(nickname);
        loginInfoVo.setAvatar(avatar);

        return R.ok().data("loginInfo", loginInfoVo);

    }

}
